Skip to content

Conversation

@dungbik
Copy link
Contributor

@dungbik dungbik commented Jul 16, 2025

📝 변경 내용


✅ 체크리스트

  • 코드가 정상적으로 동작함
  • 테스트 코드 통과함
  • 문서(README 등)를 최신화함
  • 코드 스타일 가이드 준수

💬 기타 참고 사항

Summary by CodeRabbit

  • 신규 기능

    • 사용자 정보(닉네임, 전화번호, SMS 수신 동의, 프로필 이미지) 수정 API 추가.
    • 사용자 정보 수정 요청 및 응답 모델 추가.
    • 전화번호 정규화 및 검증 유틸리티 도입(구글 libphonenumber 라이브러리 기반).
  • 버그 수정

    • 전화번호 유효성 검증 로직을 정규식에서 국제 표준 라이브러리 기반으로 개선.
  • 테스트

    • 사용자 정보 수정 관련 단위 테스트 추가.
    • 기존 전화번호 검증기 테스트 코드 삭제.
  • 기타

    • JWT 토큰에 TOKEN_VERSION 클레임 추가.
    • 빌드 파일에 libphonenumber 라이브러리 의존성 추가.

@dungbik dungbik requested a review from stoneTiger0912 July 16, 2025 05:51
@dungbik dungbik self-assigned this Jul 16, 2025
@dungbik dungbik added the enhancement New feature or request label Jul 16, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 16, 2025

Walkthrough

사용자 정보 업데이트 기능이 추가되고, 전화번호 처리 로직이 libphonenumber 라이브러리 기반으로 정교하게 개선되었습니다. JWT 토큰 생성 시 토큰 버전 정보가 추가되었으며, 관련 테스트와 유틸리티, 검증 로직, API 엔드포인트 및 모델이 신설·수정되었습니다.

Changes

파일/경로 그룹 변경 요약
src/main/java/project/flipnote/common/security/jwt/JwtComponent.java JWT 토큰 생성 시 TOKEN_VERSION 클레임 추가
src/main/java/project/flipnote/user/controller/UserController.java 사용자 정보 업데이트용 PUT 엔드포인트 추가
src/main/java/project/flipnote/user/entity/User.java 사용자 정보 갱신 메서드 update(...) 추가
src/main/java/project/flipnote/user/model/UserRegisterRequest.java getCleanedPhone() → getNormalizedPhone()로 메서드명 및 구현 변경, PhoneUtil 사용
src/main/java/project/flipnote/user/model/UserUpdateRequest.java UserUpdateRequest 레코드 신설, 필드 및 전화번호 정규화 메서드 포함
src/main/java/project/flipnote/user/model/UserUpdateResponse.java UserUpdateResponse 레코드 신설, User 엔티티로부터 생성하는 from() 메서드 포함
src/main/java/project/flipnote/user/service/UserService.java 사용자 정보 업데이트 메서드 update(...) 추가, 등록 시 전화번호 정규화 방식 변경
src/test/java/project/flipnote/user/service/UserServiceTest.java 사용자 정보 업데이트 관련 테스트 케이스 4종 추가
build.gradle libphonenumber 라이브러리(9.0.9) 의존성 추가
src/main/java/project/flipnote/common/util/PhoneUtil.java 전화번호 정규화용 PhoneUtil 유틸리티 클래스 신설
src/main/java/project/flipnote/common/validation/validator/PhoneConstraintValidator.java 전화번호 유효성 검증을 libphonenumber 기반으로 변경
src/test/java/project/flipnote/common/validator/PhoneConstraintValidatorTest.java PhoneConstraintValidatorTest 테스트 클래스 삭제

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant UserController
    participant UserService
    participant UserRepository
    participant PhoneUtil
    participant User

    Client->>UserController: PUT /v1/users (UserUpdateRequest)
    UserController->>UserService: update(userId, UserUpdateRequest)
    UserService->>UserRepository: findActiveById(userId)
    UserRepository-->>UserService: User
    UserService->>PhoneUtil: normalize(phone)
    PhoneUtil-->>UserService: normalizedPhone
    alt phone 변경됨
        UserService->>UserRepository: existsByPhone(normalizedPhone)
        UserRepository-->>UserService: boolean
        alt 이미 존재
            UserService-->>UserController: BizException(DUPLICATE_PHONE)
        end
    end
    UserService->>User: update(nickname, phone, smsAgree, profileImageUrl)
    UserService->>UserUpdateResponse: from(User)
    UserUpdateResponse-->>UserService: UserUpdateResponse
    UserService-->>UserController: UserUpdateResponse
    UserController-->>Client: 200 OK (UserUpdateResponse)
Loading

Possibly related PRs

  • FlipNoteTeam/FlipNote-BE#8: JWTComponent의 generateToken에 토큰 버전 클레임 추가 및 관련 JWT 버전 검증/관리 기능 도입과 직접적으로 연관됨.

Suggested reviewers

  • stoneTiger0912

Poem

🐰
전화번호 정규화, 업데이트도 척척!
새 엔드포인트에 토큰 버전도 쏙쏙
유틸도 늘고, 테스트도 빵빵
FlipNote는 오늘도 한 뼘 더 성장!
📱✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/main/java/project/flipnote/common/util/StringUtil.java (1)

6-12: 유틸리티 클래스 구현이 적절합니다.

StringUtil 클래스가 올바른 유틸리티 패턴으로 구현되었습니다. private 생성자와 정적 메서드 사용이 적절하고, null 처리도 안전하게 되어 있습니다.

선택적 개선사항으로, 전화번호 형식 검증 로직을 추가하는 것을 고려해보실 수 있습니다:

 public static String cleanPhone(String phone) {
-    return phone == null ? null : phone.replaceAll("-", "");
+    if (phone == null) return null;
+    String cleaned = phone.replaceAll("-", "");
+    // 선택적: 전화번호 형식 검증 추가
+    return cleaned;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a718da and f0f86ad.

📒 Files selected for processing (9)
  • src/main/java/project/flipnote/common/security/jwt/JwtComponent.java (1 hunks)
  • src/main/java/project/flipnote/common/util/StringUtil.java (1 hunks)
  • src/main/java/project/flipnote/user/controller/UserController.java (3 hunks)
  • src/main/java/project/flipnote/user/entity/User.java (1 hunks)
  • src/main/java/project/flipnote/user/model/UserRegisterRequest.java (2 hunks)
  • src/main/java/project/flipnote/user/model/UserUpdateRequest.java (1 hunks)
  • src/main/java/project/flipnote/user/model/UserUpdateResponse.java (1 hunks)
  • src/main/java/project/flipnote/user/service/UserService.java (2 hunks)
  • src/test/java/project/flipnote/user/service/UserServiceTest.java (2 hunks)
🔇 Additional comments (11)
src/main/java/project/flipnote/common/security/jwt/JwtComponent.java (1)

63-63: 토큰 버전 클레임 추가가 적절히 구현되었습니다.

JWT 토큰에 TOKEN_VERSION 클레임을 추가하여 사용자 정보 변경 시 토큰 무효화를 지원하는 보안 기능이 올바르게 구현되었습니다. 기존 토큰 검증 로직과 일관성 있게 통합되었습니다.

src/main/java/project/flipnote/user/model/UserRegisterRequest.java (2)

6-6: StringUtil 임포트 추가가 적절합니다.

전화번호 정제 로직을 중앙집중화하기 위한 임포트가 추가되었습니다.


32-34: 코드 중복 제거를 위한 리팩토링이 잘 되었습니다.

getCleanedPhone() 메서드를 StringUtil.cleanPhone()을 사용하도록 리팩토링하여 코드 재사용성과 유지보수성을 향상시켰습니다. 기존 기능은 그대로 유지되면서 중복 코드가 제거되었습니다.

src/main/java/project/flipnote/user/entity/User.java (1)

95-100: 사용자 정보 업데이트 메서드 검증 완료 및 토큰 버전 처리 확인

update() 메서드는 닉네임, 전화번호, SMS 동의 여부, 프로필 이미지만 변경하고 increaseTokenVersion()을 호출하지 않습니다.
현재 설계에서는 사용자 탈퇴(unregister()) 시에만 토큰 버전을 증가시켜 Redis 캐시를 삭제하는 흐름으로 무효화를 처리하고 있어, 프로필 수정 시 토큰 무효화가 불필요한 것으로 보입니다.

– 토큰 버전 관련 코드
User.unregister()increaseTokenVersion() 호출
UserService.unregister()tokenVersionRedisRepository.deleteTokenVersion(userId)
User.update() 에서는 의도적으로 토큰 버전 변경 없음

– 검토 사항
• 프로필 변경 시에도 보안상 세션(토큰) 무효화가 필요하다면 update()increaseTokenVersion() 및 Redis 삭제 로직 추가를 고려해주세요.
• 현행 설계대로 프로필 정보만 수정하고 토큰은 유지하는 것이 의도된 동작이라면 별도 조치 없이 머지하셔도 됩니다.

src/main/java/project/flipnote/user/controller/UserController.java (3)

8-8: PUT 매핑 임포트가 적절히 추가되었습니다.

사용자 정보 업데이트 엔드포인트를 위한 PutMapping 어노테이션 임포트가 추가되었습니다.


18-19: 요청/응답 모델 임포트가 적절히 추가되었습니다.

사용자 업데이트 기능을 위한 UserUpdateRequestUserUpdateResponse 임포트가 추가되었습니다.


41-48: 사용자 정보 업데이트 엔드포인트가 잘 구현되었습니다.

PUT /v1/users 엔드포인트가 RESTful 패턴을 따라 적절히 구현되었습니다:

  • 인증된 사용자 정보 주입 (@AuthenticationPrincipal)
  • 요청 본문 검증 (@Valid @RequestBody)
  • 적절한 HTTP 상태 코드 (200 OK)
  • 서비스 계층으로의 올바른 위임

코드가 기존 컨트롤러 패턴과 일관성 있게 작성되었습니다.

src/main/java/project/flipnote/user/service/UserService.java (1)

18-19: 새로운 모델 클래스 import가 올바르게 추가되었습니다.

사용자 정보 수정 기능을 위한 request/response 모델들이 적절히 import되었습니다.

src/main/java/project/flipnote/user/model/UserUpdateResponse.java (1)

1-18: 사용자 업데이트 응답 모델이 올바르게 구현되었습니다.

Record 클래스와 정적 팩토리 메소드가 적절히 구현되어 있으며, User 엔티티에서 응답 객체로의 매핑이 명확하고 간결합니다.

src/main/java/project/flipnote/user/model/UserUpdateRequest.java (1)

1-25: 사용자 업데이트 요청 모델이 올바르게 구현되었습니다.

적절한 validation 어노테이션이 적용되어 있고, 전화번호 정제 로직이 기존 패턴과 일관성 있게 구현되었습니다. 필드들의 필수/선택 여부도 적절히 설정되어 있습니다.

src/test/java/project/flipnote/user/service/UserServiceTest.java (1)

28-29: 테스트에 필요한 모델 클래스들이 올바르게 import되었습니다.

사용자 정보 수정 기능 테스트를 위한 request/response 모델들이 적절히 import되었습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/main/java/project/flipnote/common/validation/validator/PhoneConstraintValidator.java (1)

23-28: libphonenumber 기반 검증 로직이 잘 구현되었습니다.

검증 로직이 올바르게 구현되었으며, 예외 처리도 적절합니다. 다만 향후 다국가 지원을 고려한다면 국가 코드를 설정 가능하게 만드는 것을 검토해볼 수 있습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fad078 and 64baf8e.

📒 Files selected for processing (8)
  • build.gradle (1 hunks)
  • src/main/java/project/flipnote/common/util/PhoneUtil.java (1 hunks)
  • src/main/java/project/flipnote/common/validation/validator/PhoneConstraintValidator.java (1 hunks)
  • src/main/java/project/flipnote/user/model/UserRegisterRequest.java (2 hunks)
  • src/main/java/project/flipnote/user/model/UserUpdateRequest.java (1 hunks)
  • src/main/java/project/flipnote/user/service/UserService.java (3 hunks)
  • src/test/java/project/flipnote/common/validator/PhoneConstraintValidatorTest.java (0 hunks)
  • src/test/java/project/flipnote/user/service/UserServiceTest.java (2 hunks)
💤 Files with no reviewable changes (1)
  • src/test/java/project/flipnote/common/validator/PhoneConstraintValidatorTest.java
✅ Files skipped from review due to trivial changes (1)
  • build.gradle
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/project/flipnote/user/model/UserRegisterRequest.java
  • src/test/java/project/flipnote/user/service/UserServiceTest.java
  • src/main/java/project/flipnote/user/service/UserService.java
🔇 Additional comments (6)
src/main/java/project/flipnote/common/validation/validator/PhoneConstraintValidator.java (2)

5-7: libphonenumber 라이브러리 import가 적절합니다.

전화번호 검증에 필요한 클래스들이 정확히 import되어 있습니다.


15-15: PhoneNumberUtil 인스턴스 생성이 적절합니다.

Singleton 패턴을 사용하는 getInstance() 메서드를 적절히 활용하고 있습니다.

src/main/java/project/flipnote/common/util/PhoneUtil.java (2)

10-14: 유틸리티 클래스 설계가 우수합니다.

private constructor와 static final 필드 사용으로 유틸리티 클래스의 모범 사례를 잘 따르고 있습니다.


15-26: 전화번호 정규화 로직이 잘 구현되었습니다.

null 안전성 확보, E164 포맷 사용, 적절한 예외 처리와 한국어 에러 메시지 제공으로 견고한 구현이 완성되었습니다.

src/main/java/project/flipnote/user/model/UserUpdateRequest.java (2)

8-20: record 클래스 설계와 검증 애노테이션이 적절합니다.

각 필드에 맞는 검증 애노테이션이 적절히 적용되었으며, 선택적 필드인 profileImageUrl의 처리도 적절합니다.


22-24: 정규화된 전화번호 제공 메서드가 적절합니다.

PhoneUtil을 활용한 위임 방식으로 코드의 일관성과 재사용성을 확보했습니다.

@dungbik dungbik merged commit d6c295c into develop Jul 17, 2025
3 checks passed
@dungbik dungbik deleted the feat/user-update branch July 17, 2025 04:47
dungbik added a commit that referenced this pull request Jul 17, 2025
* Feat: 회원 정보 수정 기능

* Feat: 회원 정보 수정 단위 테스트 작성

* Fix: 전화번호를 유지한 상태로 회원 정보 수정시 예외 발생하던 오류 수정

* Test: 전화번호를 유지한 상태로 회원 정보 수정을 하는 테스트 추가

* Feat: 전화번호를 E.164 표준으로 저장되도록 수정

* Feat: 내 정보 조회 기능

* Test: UserFixture의 createActiveUser 메서드 수정

* Test: 내 정보 조회 단위 테스트 작성

* Feat: 다른 회원 정보 조회 기능

* Test: 다른 회원 정보 조회 단위 테스트 작성

* Fix: 다른 회원 정보 조회 엔드포인트 인증 필요하도록 수정

* Feat: [FN-62] 회원 정보 수정 (#9)

* Feat: 회원 정보 수정 기능

* Feat: 회원 정보 수정 단위 테스트 작성

* Fix: 전화번호를 유지한 상태로 회원 정보 수정시 예외 발생하던 오류 수정

* Test: 전화번호를 유지한 상태로 회원 정보 수정을 하는 테스트 추가

* Feat: 전화번호를 E.164 표준으로 저장되도록 수정

* Chore: develop로 rebase

* Feat: 전화번호를 E.164 표준으로 저장되도록 수정

* Feat: 내 정보 조회 기능

* Test: UserFixture의 createActiveUser 메서드 수정

* Test: 내 정보 조회 단위 테스트 작성

* Feat: 다른 회원 정보 조회 기능

* Test: 다른 회원 정보 조회 단위 테스트 작성

* Fix: 다른 회원 정보 조회 엔드포인트 인증 필요하도록 수정
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants